package com.epam.employeebase.dao.jpa;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.Query;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.JoinType;
import javax.persistence.criteria.Order;
import javax.persistence.criteria.Root;

import com.epam.employeebase.dao.IEmployeeDAO;
import com.epam.employeebase.dao.exception.DAOException;
import com.epam.employeebase.entity.Address_;
import com.epam.employeebase.entity.City_;
import com.epam.employeebase.entity.Employee;
import com.epam.employeebase.entity.Employee_;
import com.epam.employeebase.util.JPAUtil;

public final class JPAEmployeeDAO implements IEmployeeDAO{
	private static final String JPAQL_NAME_QUERY_EMPLOYEE_COUNT = "count";
	
	@Override
	public List<Employee> list(int firstEntry, int entriesNumber) throws DAOException {
		EntityManager entityManager = JPAUtil.getEntityManagerFactory().createEntityManager();
		entityManager.getTransaction().begin();
		CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
		CriteriaQuery<Employee> criteriaQuery = criteriaBuilder.createQuery(Employee.class);
		Root<Employee> root = criteriaQuery.from(Employee.class);
		root.fetch(Employee_.address, JoinType.LEFT)
			.fetch(Address_.city, JoinType.LEFT)
			.fetch(City_.country, JoinType.LEFT);
		Order order = criteriaBuilder.asc(root.get(Employee_.id));
		TypedQuery<Employee> query = entityManager.createQuery(criteriaQuery.select(root).orderBy(order));
		List<Employee> employees = query.setFirstResult(firstEntry).setMaxResults(entriesNumber).getResultList();
		entityManager.getTransaction().commit();
		return employees;
	}

	@Override
	public long employeeCount() throws DAOException {
		EntityManager entityManager = JPAUtil.getEntityManagerFactory().createEntityManager();
		entityManager.getTransaction().begin();
		Query query = entityManager.createNamedQuery(JPAQL_NAME_QUERY_EMPLOYEE_COUNT);
		long employeesNumber = (long)query.getResultList().get(0);
		entityManager.getTransaction().commit();
		return employeesNumber;
	}

}
